<?php

use \GatewayWorker\Lib\Gateway;

require_once dirname(__DIR__) . '/public.class.model.php';
class Room_Model extends Public_Model
{

    /***************************
    common function
     ***************************/


    /*
        断线
    */
    public function userDisconnected($arrData)
    {
        if(!isset($arrData['gaming_roomid']) || trim($arrData['gaming_roomid']) == G_CONST::EMPTY_STRING)
        {
            return false;
        }
        if(!isset($arrData['account_id']) || trim($arrData['account_id']) == G_CONST::EMPTY_STRING)
        {
            return false;
        }

        $room_id 		= $arrData['gaming_roomid'];
        $account_id 	= $arrData['account_id'];
        $client_id 		= $arrData['client_id'];

        if($this->queryOnlineStatus($room_id, $account_id)){
            $this->writeLog("[$room_id] [$account_id] is still in room");
            return true;
        }

        $Redis_Model = Redis_Model::getModelObject();
        $replyArr = array("[roomid]"=>$room_id,"[accountid]"=>$account_id);

        //没开局玩过的用户离线，自动从房间中退出
        if($this->queryTicketChecked($room_id, $account_id) == 0) {
            $RoomSequence_Key = strtr(Redis_Const::RoomSequence_Key, $replyArr);
            $zrem_result = $Redis_Model->zremSet($RoomSequence_Key,array($account_id));

            $account_status = Game::AccountStatus_Initial;
        } else {
            $account_status = $this->queryAccountStatus($room_id, $account_id);

            if($account_status == Game::AccountStatus_Ready){	//准备状态下断线， 变为未准备

                $account_status = Game::AccountStatus_Notready;
            }
        }

        $this->updateAccountStatus($room_id, $account_id, $account_status );
        $this->writeLog("[$room_id] ($account_id) 离线");

        //观战功能
        $RoomGuest_Key = strtr(Redis_Const::RoomGuest_Key, $replyArr);
        $Redis_Model->lremList($RoomGuest_Key,0,[$account_id]);

        //获取房间状态
        $room_status = $this->queryRoomStatus($room_id);
        if($room_status === Redis_CONST::DATA_NONEXISTENT || $room_status == Game::RoomStatus_Closed ){	//房间已经废弃或未激活
            return true;
        }

        if($room_status == Game::RoomStatus_Waiting)
        {
            $ready_count = $this->queryReadyCount($room_id);
            if($ready_count < 2){
                //取消倒计时
                $this->deleteRoomTimer($room_id);
                $arr = array("result"=>0,"operation"=>"CancelStartLimitTime","data"=>array(),"result_message"=>"取消开局倒计时");
                $this->pushMessageToGroup($room_id, $arr);
            } else {
                $this->startGame($room_id);
            }
        }

        //判断是否全部人离线
        $clients_of_groupid = Gateway::getClientSessionsByGroup($room_id);
        if(count($clients_of_groupid) == 0)
        {
            $this->setupClearRoomPassiveTimer($room_id);
        }

        return true;
    }



    /***************************
    logic function
     ***************************/

    /*
        创建房间
    */
    public function createRoom($arrData)
    {


        $timestamp = time();
        $result = array();
        $return = array();

        $data 			= $arrData['data'];
        $operation 		= $arrData['operation'];
        $account_id 	= $arrData['account_id'];
        $client_id 		= $arrData['client_id'];

        $session 		= $arrData['session'];
        $Verification_Model = Verification_Model::getModelObject();
        if(false == $Verification_Model->checkRequestSession($account_id,$session))
        {
            return OPT_CONST::NO_RETURN;
        }

        if(!isset($data['data_key']) || trim($data['data_key']) == G_CONST::EMPTY_STRING)
        {
            $this->logMessage('error', "function(createRoom):lack of data_key"." in file".__FILE__." on Line ".__LINE__);
            return $this->_missingPrameterArr($operation,"data_key");
        }

        if(!isset($data['ticket_type']) || !in_array($data['ticket_type'], [1,2]))
        {
            $this->logMessage('error', "function(createRoom):lack of ticket_type"." in file".__FILE__." on Line ".__LINE__);
            return $this->_missingPrameterArr($operation,"ticket_type");
        }
        if(!isset($data['max_count_type']) || !in_array($data['max_count_type'], [1,2]))
        {
            $this->logMessage('error', "function(createRoom):lack of max_count_type"." in file".__FILE__." on Line ".__LINE__);
            return $this->_missingPrameterArr($operation,"max_count_type");
        }
        if(!isset($data['chip_type']))
        {
            $this->logMessage('error', "function(createRoom):lack of chip_type"." in file".__FILE__." on Line ".__LINE__);
            return $this->_missingPrameterArr($operation,"chip_type");
        }
        if(!isset($data['disable_look']))
        {
            $this->logMessage('error', "function(createRoom):lack of disable_look"." in file".__FILE__." on Line ".__LINE__);
            return $this->_missingPrameterArr($operation,"disable_look");
        }
        if(!isset($data['disable_pk']))
        {
            $this->logMessage('error', "function(createRoom):lack of disable_pk"." in file".__FILE__." on Line ".__LINE__);
            return $this->_missingPrameterArr($operation,"disable_pk");
        }
        //上限
        if(!isset($data['upper_limit']) || !in_array($data['upper_limit'], [0,500,1000,2000]) )
        {
            $this->logMessage('error', "function(createRoom):lack of upper_limit"." in file".__FILE__." on Line ".__LINE__);
            return $this->_missingPrameterArr($operation,"upper_limit");
        }
        //底分
        if(!isset($data['default_score']) || !in_array($data['default_score'], [2,4,8,10,25,20,50]) )
        {
            $this->logMessage('error', "function(createRoom):lack of default_score"." in file".__FILE__." on Line ".__LINE__);
            return $this->_missingPrameterArr($operation,"default_score");
        }
        //看牌条件>=
        if(!isset($data['look_score']) || !in_array($data['look_score'], [0,100,300,500]) )
        {
            $this->logMessage('error', "function(createRoom):lack of look_score"." in file".__FILE__." on Line ".__LINE__);
            return $this->_missingPrameterArr($operation,"look_score");
        }
        //比牌条件>=
        if(!isset($data['pk_score']) || !in_array($data['pk_score'], [0,100,300,500]) )
        {
            $this->logMessage('error', "function(createRoom):lack of pk_score"." in file".__FILE__." on Line ".__LINE__);
            return $this->_missingPrameterArr($operation,"pk_score");
        }
        if(!isset($data['xipai_score'])){
//            $this->logMessage('error', "function(createRoom):lack of xipai_score"." in file".__FILE__." on Line ".__LINE__);
//            return $this->_missingPrameterArr($operation,"xipai_score");
            $data['xipai_score'] = 0;
        }
        if(!isset($data['client_name'])){
            $data['client_name'] = "wechat";
        }
        if(!isset($data['client_type'])){
            $data['client_type'] = "wechat";
        }
        if(!isset($data['daikai_id'])){
            $data['daikai_id'] = 0;
        }
        //玩法类型：1经典模式 2明牌模式
        $play_mode = isset($data['play_mode']) ? $data['play_mode'] : 1;
        //获取随机房间号
        $newRoomNumber = $this->getNewRoomNumber();
        $data_key = $data['data_key'];

        $chip_type = $data['chip_type'];
        $disable_look = $data['disable_look'];
        $disable_pk = $data['disable_pk'];
        $upper_limit = $data['upper_limit'];

        $default_score = $data['default_score'];
        $look_score = $data['look_score'];
        $pk_score = $data['pk_score'];


        //人数类型 1六人 2九人
        $max_count_type = $data['max_count_type'];
        if($max_count_type==1){
            $total_num = 10 * $data['ticket_type'];
            $room_max_count = 6;
        } else {
            $total_num = 12 * $data['ticket_type'];
            $room_max_count = 9;
        }
        //消耗数量
        $spend_ticket_count = $max_count_type * $data['ticket_type'];

        $session 		= $arrData['session'];
        $Verification_Model = Verification_Model::getModelObject();
        if(false == $Verification_Model->checkRequestSession($account_id,$session))
        {
            return OPT_CONST::NO_RETURN;
        }

        //获取维护公告
        $alert_type = -1;
        $announcement_result = $this->getGameAnnouncement($account_id);
        if(is_array($announcement_result))
        {
            $alert_type = $announcement_result['alert_type'];
            $alert_text = $announcement_result['alert_text'];
        }
        if($alert_type == 4)
        {
            $result['alert_type'] = $alert_type;
            return array("result"=>"-1","operation"=>$operation,"data"=>$result,"result_message"=>$alert_text);
        }

        $MMYSQL = $this->initMysql();

        //判断房卡余额
        $my_ticket_count = $MMYSQL->select("ticket_count")->from("room_ticket")->where("account_id=".$account_id)->single();
        $this->writeLog("($account_id) 牌券:" . $my_ticket_count);
        if($my_ticket_count >= $spend_ticket_count*Config::Ticket_Multi){

        } else {
            $this->writeLog("($account_id) 牌券不足");
            $result['alert_type'] = 1;	//1房卡不足
            return array("result"=>"1","operation"=>$operation,"data"=>$result,"result_message"=>"房卡不足");
        }

        //判断房间申请记录是否存在
        $room_where = 'data_key="'.$data_key.'"';
        $room_sql = 'select room_id,room_number,account_id,is_close from '.Room.' where '.$room_where;
        $room_query = $MMYSQL->query($room_sql);
        if(!is_array($room_query) || count($room_query) == 0 )
        {
            $room_aid = $account_id;
            $is_close = G_CONST::IS_FALSE;

            $r_array['create_time'] = $timestamp;
            $r_array['create_appid'] = "aid_".$account_id;
            $r_array['update_time'] = $timestamp;
            $r_array['update_appid'] = "aid_".$account_id;
            $r_array['is_delete'] = G_CONST::IS_FALSE;
            $r_array['data_key'] = $data_key;
            $r_array['account_id'] = $room_aid;
            $r_array['is_close'] = G_CONST::IS_FALSE;
            $r_array['max_count'] = $room_max_count;
            $r_array['game_type'] = Game::Game_Type;
            $r_array['new_room_number'] = $newRoomNumber;
            $r_array['client_name'] = $data['client_name'];
            $r_array['client_type'] = $data['client_type'];
			$r_array['daikai_id'] = $data['daikai_id'];
            $room_id = $MMYSQL->insertReturnID(Room,$r_array);
            if($room_id > 0)
            {
                //$room_number = 10000 + $room_id;
                $room_number = 100000 + $room_id * 10 + mt_rand(1,9);
            }
            else
            {
                $this->logMessage('error', "function(createRoom):用户".$account_id." 创建房间失败："." in file".__FILE__." on Line ".__LINE__);
                return array("result"=>"-1","operation"=>$operation,"data"=>$result,"result_message"=>"创建房间失败");
            }

            $num_updateSql = 'update '.Room.' set room_number="'.$room_number.'" where room_id='.$room_id;
            $num_updateQuery = $MMYSQL->query($num_updateSql);
        }
        else
        {
            $room_id = $room_query[0]['room_id'];
            $room_number = $room_query[0]['room_number'];
            $room_aid = $room_query[0]['account_id'];
            $is_close = $room_query[0]['is_close'];
        }

        //添加房间信息到redis
        $Redis_Model = Redis_Model::getModelObject();

        $replyArr = array("[roomid]"=>$room_id);
        $Room_Key = strtr(Redis_Const::Room_Key, $replyArr);

        $r_mkv[Redis_Const::Room_Field_Number] = $room_number;	//房间号
        $r_mkv[Redis_Const::Room_Field_GameRound] = 1;			//游戏轮数
        $r_mkv[Redis_Const::Room_Field_GameNum] = 0;			//游戏第几局
        $r_mkv[Redis_Const::Room_Field_MaxCount] = $room_max_count;			//游戏人数
        $r_mkv[Redis_Const::Room_Field_TotalNum] = $total_num;
        $r_mkv[Redis_Const::Room_Field_Status] = Game::RoomStatus_Waiting;				//房间状态，1等待、2进行中、3关闭
        $r_mkv[Redis_Const::Room_Field_DefaultScore] = $default_score;	//底分
        $r_mkv[Redis_Const::Room_Field_LookScore]    = $look_score;		//看牌
        $r_mkv[Redis_Const::Room_Field_pkScore] 	 = $pk_score;		//比牌

        $r_mkv[Redis_Const::Room_Field_TicketCount] = $spend_ticket_count;
        $r_mkv[Redis_Const::Room_Field_ChipType] = $chip_type;
        $r_mkv[Redis_Const::Room_Field_DisableLook] = $disable_look;
        $r_mkv[Redis_Const::Room_Field_DisablePK] = $disable_pk;
        $r_mkv[Redis_Const::Room_Field_UpperLimit] = $upper_limit;
        $r_mkv[Redis_Const::Room_Field_Creator] = $account_id;  //房间创建者
        $r_mkv[Redis_CONST::Room_Field_XiPai]        = $data['xipai_score'];
        $r_mkv[Redis_Const::Room_Field_StartTime] = -1;

        $r_mkv[Redis_Const::Room_Field_PlayMode] = $play_mode;
        $r_mkv[Redis_CONST::Room_Field_NewNumber] = $newRoomNumber;
        $mset_result = $Redis_Model->hmsetField($Room_Key,$r_mkv);
        $RedisLog_Model = Redis_Model::getModelObjectLogs();
        $RedisLog_Model->hmsetField(Redis_CONST::Room_New_Key,[$newRoomNumber=>json_encode(["room_number"=>$room_number,"game_type"=>Game::Game_Type, "create_time"=>date('Y-m-d H:i:s',$timestamp),"client_name"=>$data['client_name']])]);

        $result['room_id'] = $room_id;
        $result['room_number'] = $room_number;
        $result['is_close'] = $is_close;

        //扣除房卡  房主扣卡模式
        if(Config::Ticket_Mode == 2){
            $this->balanceTicket($room_id, $account_id, $spend_ticket_count *Config::Ticket_Multi);
        }
        //观战功能 建房时设定清房定时器
        $this->setupClearRoomPassiveTimer($room_id);
        $this->writeLog("[$room_id] ($account_id) 创建房间".$room_number);
        return array("result"=>OPT_CONST::SUCCESS,"operation"=>$operation,"data"=>$result,"result_message"=>"创建房间");
    }
    public function getNewRoomNumber(){
        $ti = microtime();
        list($s,$m) = explode(" ", $ti);
        $newRoomNumber = substr($m + substr($s,2), 4);
        if ($newRoomNumber <= 100000) $newRoomNumber += 100000;
        $RedisLog_Model = Redis_Model::getModelObjectLogs();
        if ($RedisLog_Model->hexistsField('RoomNumber',$newRoomNumber) == Redis_CONST::Key_Nonexistent){
            return $newRoomNumber;
        }else{
            return $this->getNewRoomNumber();
        }
    }

    /*
        进入房间
    */
    public function joinRoom($arrData)
    {
        $timestamp = time();
        $result = array();
        $return = array();

        $data 			= $arrData['data'];
        $operation 		= $arrData['operation'];
        $account_id 	= $arrData['account_id'];
        $client_id 		= $arrData['client_id'];

        $session 		= $arrData['session'];
        $Verification_Model = Verification_Model::getModelObject();
        if(false == $Verification_Model->checkRequestSession($account_id,$session))
        {
            return OPT_CONST::NO_RETURN;
        }

        if(!(isset($data['room_number'])&& $data['room_number'] > 0) )
        {
            $this->logMessage('error', "function(joinRoom):lack of room_number"." in file".__FILE__." on Line ".__LINE__);
            return $this->_missingPrameterArr($operation,"room_number");
        }

        $room_number = $data['room_number'];

        //判断房间是否存在
        $MMYSQL = $this->initMysql();
        $room_sql = 'select room_id,account_id,is_close,max_count from '.Room.' where room_number='.$room_number;
        $room_row = $MMYSQL->row($room_sql);
        if(!$room_row){
            $this->logMessage('error', "function(joinRoom):room($room_number) not exist"." in file".__FILE__." on Line ".__LINE__);
            return array("result"=>OPT_CONST::FAILED,"operation"=>$operation,"data"=>$result,"result_message"=>"房间不存在");
        } else {
            $room_id = $room_row['room_id'];
            $room_max_count = $room_row['max_count'];
            if($room_row['is_close']){
                $result = array('room_status'=>4);
                return array("result"=>0, "operation"=>$operation,"data"=>$result,"result_message"=>"房间已关闭");
            }
        }

        $Redis_Model = Redis_Model::getModelObject();
        $replyArr = array("[roomid]"=>$room_id,"[accountid]"=>$account_id);

        $RoomSequence_Key = strtr(Redis_Const::RoomSequence_Key, $replyArr);

        //总分数
        $RoomScore_Key = strtr(Redis_Const::RoomScore_Key, $replyArr);
        $RoomScore_Field_User = strtr(Redis_Const::RoomScore_Field_User, $replyArr);

        $rsSeq_score = $Redis_Model->getZscore($RoomSequence_Key,$account_id);
        //判断用户是否已加入房间
        if(Redis_CONST::DATA_NONEXISTENT !== $rsSeq_score)		//已加入
        {
            //获取分数
            $rScore_score = $Redis_Model->hgetField($RoomScore_Key,$RoomScore_Field_User);
            //获取用户所在位置
            $serial_num = $rsSeq_score;

            $account_status = $this->queryAccountStatus($room_id, $account_id);
        }
        else	//未加入
        {
            $serial_num = $this->joinRoomTransaction($room_id,$account_id, $room_max_count);
            if(!$serial_num){
                $result['alert_type'] = 2;
                return array("result"=>"1","operation"=>$operation,"data"=>$result,"result_message"=>"房间人数已满");
            }

            //添加默认分数
            $rScore_score = 0;
            $rScore_mkv[$RoomScore_Field_User] = $rScore_score;
            $hmset_result = $Redis_Model->hmsetField($RoomScore_Key,$rScore_mkv);

            //首次进房初始状态
            $account_status =  Game::AccountStatus_Initial;
            $AccountStatus_Key = strtr(Redis_Const::AccountStatus_Key, $replyArr);
            $mkv[$account_id] = $account_status;
            $mset_result = $Redis_Model->hmsetField($AccountStatus_Key,$mkv);

        }

        //绑定用户UID
        $RoomUser_UID = strtr(Game::RoomUser_UID, $replyArr);
        Gateway::bindUid($client_id, $RoomUser_UID);
        Gateway::joinGroup($client_id, $room_id);

        //获取房间当前局数
        $setting = $this->queryRoomSetting($room_id);
        $game_num = $setting[Redis_CONST::Room_Field_GameNum];
        $total_num = $setting[Redis_CONST::Room_Field_TotalNum];
        $room_status = $setting[Redis_CONST::Room_Field_Status];
        $scoreboard_str = $setting[Redis_CONST::Room_Field_Scoreboard];
        $scoreboard = json_decode($scoreboard_str);
        $play_mode = $setting[Redis_CONST::Room_Field_PlayMode];

        $room_ary['room_id'] = $room_id;
        $room_ary['room_number'] = $room_number;
        $room_ary['room_status'] = $room_status;
        $room_ary['account_score'] = $rScore_score;
        $room_ary['account_status'] = $account_status;
        $room_ary['online_status'] = $this->queryOnlineStatus($room_id, $account_id);

        $room_ary['serial_num'] = $serial_num;
        $room_ary['game_num'] = $game_num;
        $room_ary['total_num'] = $total_num;
        $room_ary['xipai_score']    = $setting[Redis_Const::Room_Field_XiPai];
        $room_ary['ticket_checked'] = $this->queryTicketChecked($room_id, $account_id);
        $room_ary['scoreboard'] = $scoreboard;
        $room_ary['creator_id'] = $setting[Redis_CONST::Room_Field_Creator];

        $card_info = array();
        $card_type = 0;
        if($this->querySeenCard($room_id, $account_id)){	//已经看过牌的
            $card_info = $this->queryCardInfo($room_id, $account_id);
            $value = $this->caculateCardValue($room_id, $account_id);
            $card_type = substr($value, 0, 1);
        } else if($play_mode==2 && $account_status==Game::AccountStatus_Invisible){ //明牌模式显示头两张牌
            $card_info = $this->queryCardInfo($room_id, $account_id);
            $card_info[2] = "-1";
        } //明牌

        $room_ary['cards'] = $card_info;
        $room_ary['card_type'] = $card_type;

        $room_ary['benchmark'] = $this->queryBenchmark($room_id);
        $room_ary['pool_score'] = $this->queryPoolScore($room_id);

        $room_ary['ticket_count'] =   $setting[Redis_Const::Room_Field_TicketCount];
        $room_ary['chip_type']    =   $setting[Redis_Const::Room_Field_ChipType];
        $room_ary['disable_look'] =   $setting[Redis_Const::Room_Field_DisableLook];
        $room_ary['disable_pk']   =   $setting[Redis_Const::Room_Field_DisablePK];
        $room_ary['upper_limit']    = $setting[Redis_Const::Room_Field_UpperLimit];

        //推送房间信息
        $room_return = array("result"=>OPT_CONST::SUCCESS,"operation"=>$operation,"data"=>$room_ary,"result_message"=>"入房成功");
        $this->pushMessageToCurrentClient($room_return);

        //返回所有玩家状态给进房玩家
        $allGamer = $this->getGamerInfo($room_id);
        if(is_array($allGamer))
        {
            $currentGamer_return = array("result"=>OPT_CONST::SUCCESS,"operation"=>"AllGamerInfo","data"=>$allGamer,"result_message"=>"所有玩家状态");
            $this->pushMessageToCurrentClient($currentGamer_return);
        }

        $this->notyfyPlayingStatus($room_id, $account_id);

        //观战功能  从观战列表删除
        $RoomGuest_Key = strtr(Redis_Const::RoomGuest_Key, $replyArr);
        $Redis_Model->lremList($RoomGuest_Key,0,[$account_id]);
        //返回所有观战者给当前玩家
        $allGuest = $this->getGuestInfo($room_id);
        if(is_array($allGuest))
        {
            $currentGamer_return = array("result"=>OPT_CONST::SUCCESS,"operation"=>"AllGuestInfo","data"=>$allGuest,"result_message"=>"所有观战者状态");
            $this->pushMessageToCurrentClient($currentGamer_return);
        }

        //推送当前玩家状态给其他玩家
        $currentGamer = $this->getGamerInfo($room_id,$account_id);
        if(is_array($currentGamer))
        {
            $currentGamer_return = array("result"=>OPT_CONST::SUCCESS,"operation"=>"UpdateGamerInfo","data"=>$currentGamer,"result_message"=>"某玩家状态");
            $this->pushMessageToGroup($room_id, $currentGamer_return, $client_id);
        }

        //显示房间目前的倒计时
        $limit = $game_num > 0 ? Game::LimitTime_Ready : Game::LimitTime_StartGame;

        if($room_status == Game::RoomStatus_Waiting && ($countdown = $this->queryCountdown($room_id, $limit)) > 0){
            $arr = array("result"=>0,"operation"=>"StartLimitTime","data"=>array('limit_time' => $countdown),"result_message"=>"开始倒计时");
            $this->pushMessageToCurrentClient($arr);
        }

        //保存用户当前房间,用户ID
        $_SESSION['gaming_roomid'] = $room_id;
        $_SESSION['account_id'] = $account_id;

        $this->writeLog("[$room_id] $account_id 进入房间");
        return OPT_CONST::NO_RETURN;
    }

    protected function joinRoomTransaction($room_id,$account_id,$max_count)
    {
        $Redis_Model = Redis_Model::getModelObject();
        $replyArr = array("[roomid]"=>$room_id);
        $key = strtr(Redis_Const::RoomSequence_Key, $replyArr);

        $redisAuth = $Redis_Model->pingRedisAuth();
        if($redisAuth === G_CONST::EMPTY_STRING || !is_object($redisAuth))
        {
            $this->logMessage('error', "function(joinRoomTransaction):redisAuth is empty string"." in file".__FILE__." on Line ".__LINE__);
            return false;
        }

        $success = false;
        $options = array(
            'cas'   => true,    // Initialize with support for CAS operations
            'watch' => $key,    // Key that needs to be WATCHed to detect changes
            'retry' => 3,       // Number of retries on aborted transactions, after
            // which the client bails out with an exception.
        );

        $redisAuth->transaction($options, function ($tx) use ($key,$account_id, $max_count, &$success) {
            $result = $tx->zrange($key,0,-1,'withscores');
            if(is_array($result)) {
                if(count($result) >= $max_count){
                    $this->writeLog("joinRoom: accountid".$account_id." 人数已满 ".__FILE__.__LINE__);
                    $success = false;
                } else {
                    for($serial_num=1;$serial_num<=$max_count;$serial_num++){
                        if(array_search($serial_num,$result) === false){
                            $tx->multi();   // With CAS, MULTI *must* be explicitly invoked.
                            $zadd_result = $tx->zadd($key,$serial_num,$account_id);
                            $success = $serial_num;
                            break;
                        }
                    }
                }
            } else {
                $this->writeLog("joinRoom:zrange result error ".__FILE__.__LINE__);
                $success = false;
            }
        });
        return $success;
    }

    protected function notyfyPlayingStatus($room_id, $account_id)
    {
        $Redis_Model = Redis_Model::getModelObject();
        $replyArr = array("[roomid]"=>$room_id,"[accountid]"=>$account_id);
        $active_user =  $this->queryActiveUser($room_id);
        if($active_user != -1){

            $cond = $this->lookPkConditon($room_id, $active_user);
            $can_pk = $cond['can_pk'];
            $can_look = $cond['can_look'];
            $can_open = 0;
            $pk_user = array();
            if($can_pk){
                $pk_user = $this->queryPkUser($room_id, $active_user);
                if(count($pk_user) > 0){
                    $can_open = 1;
                }
            }

            //通知:哪位正进行下注
            $noty_arr = array(
                'account_id' => $active_user,
                'playing_status' => Game::PlayingStatus_Betting,
                'limit_time'	 => $this->queryCountdown($room_id, Game::LimitTime_Betting),
                'can_open' => $can_open,
                'pk_user' => $pk_user,
                'can_look' => $can_look
            );
            $msg_arr = array("result"=>0,"operation"=>"NotyChooseChip","data"=>$noty_arr,"result_message"=>"通知下注");
            $this->pushMessageToCurrentClient($msg_arr);
        }
    }

    /*
        观战功能 进入观战
    */
    public function guestRoom($arrData)
    {
        $timestamp = time();
        $result = array();
        $return = array();

        $data 			= $arrData['data'];
        $operation 		= $arrData['operation'];
        $account_id 	= $arrData['account_id'];
        $client_id 		= $arrData['client_id'];

        $session 		= $arrData['session'];
        $Verification_Model = Verification_Model::getModelObject();
        if(false == $Verification_Model->checkRequestSession($account_id,$session))
        {
            return OPT_CONST::NO_RETURN;
        }

        if(!(isset($data['room_number'])&& $data['room_number'] > 0) )
        {
            $this->writeLog(__FUNCTION__.":lack of room_number"." in file".__FILE__." on Line ".__LINE__);
            return $this->_missingPrameterArr($operation,"room_number");
        }

        $room_number = $data['room_number'];

        //判断房间是否存在
        $MMYSQL = $this->initMysql();
        $room_sql = 'select room_id,account_id,is_close,max_count from '.Room.' where room_number='.$room_number;
        $room_row = $MMYSQL->row($room_sql);
        if(!$room_row){
            $this->writeLog(__FUNCTION__.":room($room_number) not exist"." in file".__FILE__." on Line ".__LINE__);
            return array("result"=>OPT_CONST::FAILED,"operation"=>$operation,"data"=>$result,"result_message"=>"房间不存在");
        } else {
            $room_id = $room_row['room_id'];
            $room_max_count = $room_row['max_count'];
            if($room_row['is_close']){
                $result = array('room_status'=>4);
                return array("result"=>0, "operation"=>$operation,"data"=>$result,"result_message"=>"房间已关闭");
            }
        }

        $Redis_Model = Redis_Model::getModelObject();
        $replyArr = array("[roomid]"=>$room_id,"[accountid]"=>$account_id);
        $RoomGuest_Key = strtr(Redis_Const::RoomGuest_Key, $replyArr);

        $guests = $this->queryGuestList($room_id);
        //判断用户是否已加入观战
        if(!in_array($account_id, $guests)){
            $Redis_Model->pushList(1,0,$RoomGuest_Key,[$account_id]);
        }

        //绑定用户UID
        $RoomUser_UID = strtr(Game::RoomUser_UID, $replyArr);
        Gateway::bindUid($client_id, $RoomUser_UID);
        Gateway::joinGroup($client_id, $room_id);

        //获取房间当前局数
        $setting = $this->queryRoomSetting($room_id);
        $game_num = $setting[Redis_CONST::Room_Field_GameNum];
        $total_num = $setting[Redis_CONST::Room_Field_TotalNum];
        $room_status = $setting[Redis_CONST::Room_Field_Status];
        $scoreboard_str = $setting[Redis_CONST::Room_Field_Scoreboard];
        $scoreboard = json_decode($scoreboard_str);
        $play_mode = $setting[Redis_CONST::Room_Field_PlayMode];

        $room_ary['room_id'] = $room_id;
        $room_ary['room_status'] = $room_status;
        $room_ary['game_num'] = $game_num;
        $room_ary['total_num'] = $total_num;
        $room_ary['scoreboard'] = $scoreboard;

        $room_ary['benchmark'] = $this->queryBenchmark($room_id);
        $room_ary['pool_score'] = $this->queryPoolScore($room_id);

        $room_ary['chip_type']    =   $setting[Redis_Const::Room_Field_ChipType];
        $room_ary['disable_look'] = $setting[Redis_Const::Room_Field_DisableLook];
        $room_ary['disable_pk'] = $setting[Redis_Const::Room_Field_DisablePK];
        $room_ary['upper_limit']    = $setting[Redis_Const::Room_Field_UpperLimit];
        $room_ary['creator_id'] =$setting[Redis_Const::Room_Field_Creator];
        //推送房间信息
        $room_return = array("result"=>OPT_CONST::SUCCESS,"operation"=>$operation,"data"=>$room_ary,"result_message"=>"入房成功");
        $this->pushMessageToCurrentClient($room_return);

        $RoomSequence_Key = strtr(Redis_Const::RoomSequence_Key, $replyArr);
        $rsSeq_score = $Redis_Model->getZscore($RoomSequence_Key,$account_id);
        //已加入房间的
        if(Redis_CONST::DATA_NONEXISTENT !== $rsSeq_score){
            if($this->queryTicketChecked($room_id, $account_id) == 0) {
                $Redis_Model->zremSet($RoomSequence_Key,array($account_id));
            }
            $this->writeLog("[$room_id] ($account_id) 玩家变为观战者");
        }

        //返回所有玩家状态给当前玩家
        $allGamer = $this->getGamerInfo($room_id);
        if(is_array($allGamer))
        {
            $currentGamer_return = array("result"=>OPT_CONST::SUCCESS,"operation"=>"AllGamerInfo","data"=>$allGamer,"result_message"=>"所有玩家状态");
            $this->pushMessageToCurrentClient($currentGamer_return);
        }

        $this->notyfyPlayingStatus($room_id, $account_id);

        //返回所有观战者给当前玩家
        $allGuest = $this->getGuestInfo($room_id);
        if(is_array($allGuest))
        {
            $currentGamer_return = array("result"=>OPT_CONST::SUCCESS,"operation"=>"AllGuestInfo","data"=>$allGuest,"result_message"=>"所有观战者状态");
            $this->pushMessageToCurrentClient($currentGamer_return);
        }

        //推送当前观战者给其他玩家
        $account_sql = 'select nickname,headimgurl from '.WX_Account.' where account_id="'.$account_id.'"';
        $row = $MMYSQL->row($account_sql);
        if($row){
            $guest = array(
                'account_id' => $account_id,
                'nickname'   => $row['nickname'],
                'headimgurl' => $row['headimgurl'],
                'is_guest'   => "1"
            );
            $guest_return = array("result"=>OPT_CONST::SUCCESS,"operation"=>"UpdateGuestInfo","data"=>$guest,"result_message"=>"某观战者状态");
            $this->pushMessageToGroup($room_id, $guest_return, $client_id);
        } else {
            $this->writeLog("推送当前观战者:account($account_id) not exist".__FILE__.__LINE__);
        }

        //显示房间目前的倒计时
        $limit = $game_num > 0 ? Game::LimitTime_Ready : Game::LimitTime_StartGame;
        if($room_status == Game::RoomStatus_Waiting && ($countdown = $this->queryCountdown($room_id, $limit)) > 0){
            $arr = array("result"=>0,"operation"=>"StartLimitTime","data"=>array('limit_time' => $countdown),"result_message"=>"开始倒计时");
            $this->pushMessageToCurrentClient($arr);
        }

        //保存用户当前房间,用户ID
        $_SESSION['gaming_roomid'] = $room_id;
        $_SESSION['account_id'] = $account_id;

        $this->startGame($room_id);

        $this->writeLog("[$room_id] ($account_id) 观战");
        return OPT_CONST::NO_RETURN;
    }
    /*
        获取观战者
    */
    protected function getGuestInfo($room_id)
    {
        $result = array();
        $MMYSQL = $this->initMysql();

        //观战者列表
        $guests = $this->queryGuestList($room_id);

        if(count($guests)>0){
            $account_sql = 'select account_id,nickname,headimgurl from '.WX_Account.' where account_id in ('.implode(",", $guests).')';
            $rows = $MMYSQL->query($account_sql);
            if(is_array($rows)){
                foreach ($rows as $item) {
                    $info['account_id'] = $item['account_id'];
                    $info['nickname'] = $item['nickname'];
                    $info['headimgurl'] = $item['headimgurl'];
                    $result[] = $info;
                }
            }
        }
        return $result;
    }

    /*
        拉取房间信息
    */
    public function pullRoomInfo($arrData)
    {
        $result = array();

        $data 			= $arrData['data'];
        $operation 		= $arrData['operation'];
        $account_id 	= $arrData['account_id'];
        $client_id 		= $arrData['client_id'];

        $session 		= $arrData['session'];
        $Verification_Model = Verification_Model::getModelObject();
        if(false == $Verification_Model->checkRequestSession($account_id,$session))
        {
            return OPT_CONST::NO_RETURN;
        }

        if(!(isset($data['room_id'])&& $data['room_id'] > 0) )
        {
            $this->logMessage('error', "function(pullRoomInfo):lack of room_id"." in file".__FILE__." on Line ".__LINE__);
            return $this->_missingPrameterArr($operation,"room_id");
        }

        $room_id = $data['room_id'];

        $is_legal = $this->checkRequestClientLegal($client_id,$room_id,$account_id);
        if(!$is_legal)
        {
            $this->logMessage('error', "function(checkRequestClientLegal):illegal opt: account_id($account_id) room_id($room_id)"." in file".__FILE__." on Line ".__LINE__);
            //推送强制下线
            $illegal_message = $this->_JSON(array("result"=>"-203","result_message"=>"illegal opt"));
            Gateway::sendToCurrentClient($illegal_message);
            return OPT_CONST::NO_RETURN;
        }

        $Redis_Model = Redis_Model::getModelObject();
        $replyArr = array("[roomid]"=>$room_id,"[accountid]"=>$account_id);

        $RoomSequence_Key = strtr(Redis_Const::RoomSequence_Key, $replyArr);

        //总分数
        $RoomScore_Key = strtr(Redis_Const::RoomScore_Key, $replyArr);
        $RoomScore_Field_User = strtr(Redis_Const::RoomScore_Field_User, $replyArr);

        $rsSeq_score = $Redis_Model->getZscore($RoomSequence_Key,$account_id);
        //判断用户是否已加入房间
        if(Redis_CONST::DATA_NONEXISTENT !== $rsSeq_score)		//已加入
        {
            //获取分数
            $rScore_score = $Redis_Model->hgetField($RoomScore_Key,$RoomScore_Field_User);
            //获取用户所在位置
            $serial_num = $rsSeq_score;

            $account_status = $this->queryAccountStatus($room_id, $account_id);
        }
        else	//未加入
        {
            $this->logMessage('error', "function(pullRoomInfo):account($account_id) not join room"." in file".__FILE__." on Line ".__LINE__);
            return array("result"=>OPT_CONST::FAILED,"operation"=>$operation,"data"=>$result,"result_message"=>"用户未加入房间");
        }

        $setting = $this->queryRoomSetting($room_id);
        $play_mode = $setting[Redis_CONST::Room_Field_PlayMode];

        $room_ary['account_score'] = $rScore_score;
        $room_ary['account_status'] = $account_status;
        $room_ary['online_status'] = $this->queryOnlineStatus($room_id, $account_id);

        $room_ary['serial_num'] = $serial_num;

        $room_ary['ticket_checked'] = $this->queryTicketChecked($room_id, $account_id);

        $card_info = array();
        $card_type = 0;
        if($this->querySeenCard($room_id, $account_id)){	//已经看过牌的
            $card_info = $this->queryCardInfo($room_id, $account_id);
            $value = $this->caculateCardValue($room_id, $account_id);
            $card_type = substr($value, 0, 1);
        } else if($play_mode==2 && $account_status==Game::AccountStatus_Invisible){ //明牌模式显示头两张牌
            $card_info = $this->queryCardInfo($room_id, $account_id);
            $card_info[2] = "-1";
        }  //明牌

        $room_ary['cards'] = $card_info;
        $room_ary['card_type'] = $card_type;

        $room_ary['benchmark'] = $this->queryBenchmark($room_id);
        $room_ary['pool_score'] = $this->queryPoolScore($room_id);

        $room_ary['chip_type'] = $setting[Redis_Const::Room_Field_ChipType];

        //返回所有玩家状态
        $allGamer = $this->getGamerInfo($room_id);
        if(!is_array($allGamer))
        {
            $this->logMessage('error', "function(pullRoomInfo):room($room_id) no player"." in file".__FILE__." on Line ".__LINE__);
            return array("result"=>OPT_CONST::FAILED,"operation"=>$operation,"data"=>$result,"result_message"=>"房间没有其他用户");
        }

        $pull_return = array("result"=>OPT_CONST::SUCCESS,"operation"=>$operation,"data"=>$room_ary,"result_message"=>"拉取房间信息","all_gamer_info"=>$allGamer);

        $this->pushMessageToCurrentClient($pull_return);

        $this->notyfyPlayingStatus($room_id, $account_id);

        $this->logMessage('error', "function(pullRoomInfo):用户$account_id 拉取房间$room_id 信息"." in file".__FILE__." on Line ".__LINE__);
        $this->logMessage('error', "function(pullRoomInfo):pull_return:".json_encode($pull_return). " in file".__FILE__." on Line ".__LINE__);

        return OPT_CONST::NO_RETURN;
    }

    /*
        获取房间所有用户
    */
    protected function getGamerInfo($room_id,$account_id=-1)
    {
        $result = array();

        $Redis_Model = Redis_Model::getModelObject();
        $MMYSQL = $this->initMysql();

        $replyArr = array("[roomid]"=>$room_id,"[accountid]"=>$account_id);

        //房间玩家集合
        $RoomSequence_Key = strtr(Redis_Const::RoomSequence_Key, $replyArr);

        //获取房间所有用户
        $sset_array['key'] = $RoomSequence_Key;
        $sset_array['WITHSCORES'] = "WITHSCORES";
        $gamer_query = $Redis_Model->getSortedSetLimitByAry($sset_array);
        if(Redis_CONST::DATA_NONEXISTENT !== $gamer_query)
        {
            foreach($gamer_query as $gamer_id=>$serial_num)
            {
                //获取玩家信息
                $account_where = 'account_id="'.$gamer_id.'"';
                $account_sql = 'select nickname,headimgurl from '.WX_Account.' where '.$account_where;
                $account_query = $MMYSQL->query($account_sql);
                if(!is_array($account_query) || count($account_query) == 0 )
                {
                    $this->logMessage('error', "function(getGamerInfo):account($gamer_id) not exist"." in file".__FILE__." on Line ".__LINE__);
                    return false;
                }
                $info['serial_num'] = $serial_num;
                $info['account_id'] = $gamer_id;
                $info['nickname'] = $account_query[0]['nickname'];
                $info['headimgurl'] = $account_query[0]['headimgurl'];


                //获取玩家当前积分
                $rScore_score = $this->queryAccountScore($room_id, $gamer_id);
                if(Redis_CONST::DATA_NONEXISTENT === $rScore_score)
                {
                    $this->logMessage('error', "function(getGamerInfo):account($gamer_id) score not exist"." in file".__FILE__." on Line ".__LINE__);
                    return false;
                }
                $info['account_score'] = $rScore_score;

                //获取玩家当前状态
                $rStatus = $this->queryAccountStatus($room_id, $gamer_id);
                if(Redis_CONST::DATA_NONEXISTENT === $rStatus)
                {
                    $this->logMessage('error', "function(getGamerInfo):account($gamer_id) status not exist"." in file".__FILE__." on Line ".__LINE__);
                    return false;
                }
                $info['account_status'] = $rStatus;
                $info['online_status'] = $this->queryOnlineStatus($room_id, $gamer_id);
                $info['ticket_checked'] = $this->queryTicketChecked($room_id, $gamer_id);

                if($account_id == $gamer_id)
                {
                    return $info;
                }

                $result[] = $info;

            }
        }

        return $result;
    }


    /*
        进房之前的查询
    */
    public function prepareJoinRoom($arrData)
    {
        $result = array();

        $data 			= $arrData['data'];
        $operation 		= $arrData['operation'];
        $account_id 	= $arrData['account_id'];

        $session 		= $arrData['session'];
        $Verification_Model = Verification_Model::getModelObject();
        if(false == $Verification_Model->checkRequestSession($account_id,$session))
        {
            return OPT_CONST::NO_RETURN;
        }

        if(!(isset($data['room_number'])&& $data['room_number'] > 0) )
        {
            $this->logMessage('error', "function(PrepareJoinRoom):lack of room_number"." in file".__FILE__." on Line ".__LINE__);
            return $this->_missingPrameterArr($operation,"room_number");
        }

        $room_number = $data['room_number'];

        //判断房间是否存在
        $MMYSQL = $this->initMysql();
        $room_sql = 'select room_id,account_id,is_close,max_count from '.Room.' where room_number='.$room_number;
        $room_row = $MMYSQL->row($room_sql);
        if(!$room_row){
            $this->logMessage('error', "function(joinRoom):room($room_number) not exist"." in file".__FILE__." on Line ".__LINE__);
            return array("result"=>OPT_CONST::FAILED,"operation"=>$operation,"data"=>$result,"result_message"=>"房间不存在");
        } else {
            $room_id = $room_row['room_id'];
            $room_max_count = $room_row['max_count'];
            if($room_row['is_close']){
                $result = array('room_status'=>4);
                return array("result"=>0, "operation"=>$operation,"data"=>$result,"result_message"=>"房间已关闭");
            }
        }

        //房间参数
        $user_count = 0;
        $alert_text = "";
        $setting = $this->queryRoomSetting($room_id);
        $room_array = array(
            'user_count'=>$user_count,
            'alert_text' => $alert_text,
            'room_status'    => $setting[Redis_Const::Room_Field_Status],
            'ticket_count'   => $setting[Redis_Const::Room_Field_TicketCount],
            'chip_type'      => $setting[Redis_Const::Room_Field_ChipType],
            'disable_look'   => $setting[Redis_Const::Room_Field_DisableLook],
            'disable_pk'     => $setting[Redis_Const::Room_Field_DisablePK],
            'upper_limit'    => $setting[Redis_Const::Room_Field_UpperLimit],
            'play_mode'      => $setting[Redis_Const::Room_Field_PlayMode],
            'default_score'  => $setting[Redis_Const::Room_Field_DefaultScore],
            'look_score'     => $setting[Redis_Const::Room_Field_LookScore],
            'pk_score'       => $setting[Redis_Const::Room_Field_pkScore],
            'xipai_score'    => $setting[Redis_Const::Room_Field_XiPai],
            'creator_id'     => $setting[Redis_Const::Room_Field_Creator],
        );

        //获取维护公告
        $alert_type = -1;
        $announcement_result = $this->getGameAnnouncement($account_id);
        if(is_array($announcement_result))
        {
            $alert_type = $announcement_result['alert_type'];
            $alert_text = $announcement_result['alert_text'];
        }
        if($alert_type == 4)
        {
            $room_array['alert_type'] = $alert_type;
            return array("result"=>"1","operation"=>$operation,"data"=>$room_array,"result_message"=>$alert_text);
        }


        $Redis_Model = Redis_Model::getModelObject();
        $replyArr = array("[roomid]"=>$room_id,"[accountid]"=>$account_id);
        $RoomSequence_Key = strtr(Redis_Const::RoomSequence_Key, $replyArr);
        $RoomGuest_Key = strtr(Redis_Const::RoomGuest_Key, $replyArr);

        //房间人
        $room_users = array();
        $is_member = false;
        //获取房间所有用户
        $sset_array['key'] = $RoomSequence_Key;
        $gamer_query = $Redis_Model->getSortedSetLimitByAry($sset_array);
        if(Redis_CONST::DATA_NONEXISTENT !== $gamer_query && count($gamer_query)>0)
        {
            $account_sql = 'select account_id,nickname from '.WX_Account.' where account_id in ('.implode(",", $gamer_query).')';
            $rows = $MMYSQL->query($account_sql);
            if(is_array($rows)){
                foreach ($rows as $item) {
                    $room_users[] = $item['nickname'];
                    $user_count++;
                    if($item['account_id'] == $account_id){
                        $is_member = true;
                    }
                }
            }
        }

        //观战功能
        //获取房间参观者数量
        $guest_count = $Redis_Model->llenList($RoomGuest_Key);
        $room_array['is_member'] = $is_member;
        $room_array['can_join'] = $user_count < $room_max_count;
        $room_array['can_guest'] = $guest_count < Config::Guest_MaxCount;
        $room_array['room_users'] = $room_users;

        return array("result"=>"0","operation"=>$operation,"data"=>$room_array,"result_message"=>"进房询问");
    }

    protected function getGameAnnouncement($account_id)
    {
        //var_dump($account_id);

        $timestamp = time();

        $MMYSQL = $this->initMysql();

        $game_type = Game::Game_Type;

        $announcement_where = 'game_type='.$game_type.' and announce_time<='.$timestamp.' and end_time>'.$timestamp.' and is_delete=0';
        $announcement_sql = 'select announce_time,service_time,end_time,announce_text,service_text from '.Game_Announcement.' where '.$announcement_where;
        $announcement_query = $MMYSQL->query($announcement_sql);
        if(is_array($announcement_query) && count($announcement_query) > 0)
        {
            $announce_time = $announcement_query[0]['announce_time'];
            $service_time = $announcement_query[0]['service_time'];
            $end_time = $announcement_query[0]['end_time'];
            $announce_text = $announcement_query[0]['announce_text'];
            $service_text = $announcement_query[0]['service_text'];

            if($timestamp >= $service_time)
            {
                $array['alert_type'] = 4;
                $array['alert_text'] = $service_text;
            }
            else
            {
                $array['alert_type'] = 4;
                $array['alert_text'] = $announce_text;
            }

            //获取白名单用户
            $whilelist_sql = 'select data_id from '.Game_Whilelist.' where account_id='.$account_id.' and is_delete=0';
            $whilelist_query = $MMYSQL->query($whilelist_sql);
            if(is_array($whilelist_query) && count($whilelist_query) > 0)
            {
                $this->logMessage('error', "function(getGameAnnouncement):白名单用户:".$account_id." in file".__FILE__." on Line ".__LINE__);
                return true;
            }
            else
            {
                return $array;
            }
        }

        return true;
    }


    /*
        准备操作
    */
    public function readyStart($arrData)
    {
        $timestamp = time();
        $result = array();
        $return = array();

        $data 			= $arrData['data'];
        $operation 		= $arrData['operation'];
        $account_id 	= $arrData['account_id'];
        $client_id 		= $arrData['client_id'];

        $session 		= $arrData['session'];
        $Verification_Model = Verification_Model::getModelObject();
        if(false == $Verification_Model->checkRequestSession($account_id,$session))
        {
            return OPT_CONST::NO_RETURN;
        }

        if(!isset($data['room_id']) || trim($data['room_id']) == G_CONST::EMPTY_STRING)
        {
            $this->logMessage('error', "function(readyStart):lack of room_id"." in file".__FILE__." on Line ".__LINE__);
            return $this->_missingPrameterArr($operation,"room_id");
        }

        $room_id = $data['room_id'];

        $is_legal = $this->checkRequestClientLegal($client_id,$room_id,$account_id);
        if(!$is_legal)
        {
            $this->logMessage('error', "function(checkRequestClientLegal):illegal opt: account_id($account_id) room_id($room_id)"." in file".__FILE__." on Line ".__LINE__);
            //推送强制下线
            $illegal_message = $this->_JSON(array("result"=>"-203","result_message"=>"illegal opt"));
            Gateway::sendToCurrentClient($illegal_message);
            return OPT_CONST::NO_RETURN;
        }

        $Redis_Model = Redis_Model::getModelObject();
        $replyArr = array("[roomid]"=>$room_id,"[accountid]"=>$account_id);

        //获取玩家当前状态，是否未准备
        $rStatus = $this->queryAccountStatus($room_id, $account_id);
        if(Redis_CONST::DATA_NONEXISTENT === $rStatus || !in_array($rStatus, [Game::AccountStatus_Initial, Game::AccountStatus_Notready])  )
        {
            $this->writeLog("function(readyStart):account($account_id) status($rStatus) invalid"." in file".__FILE__." on Line ".__LINE__);
            return array("result"=>OPT_CONST::FAILED,"operation"=>$operation,"data"=>$result,"result_message"=>"状态异常");
        }

        //更新用户状态
        $rStatus = Game::AccountStatus_Ready;
        $this->updateAccountStatus($room_id, $account_id, $rStatus);

        $this->startGame($room_id);

        return OPT_CONST::NO_RETURN;
    }

    /*
        取消准备操作
    */
    public function readyCancel($arrData)
    {
        $timestamp = time();
        $result = array();
        $return = array();

        $data 			= $arrData['data'];
        $operation 		= $arrData['operation'];
        $account_id 	= $arrData['account_id'];
        $client_id 		= $arrData['client_id'];

        $session 		= $arrData['session'];
        $Verification_Model = Verification_Model::getModelObject();
        if(false == $Verification_Model->checkRequestSession($account_id,$session))
        {
            return OPT_CONST::NO_RETURN;
        }

        if(!isset($data['room_id']) || trim($data['room_id']) == G_CONST::EMPTY_STRING)
        {
            $this->logMessage('error', "function(readyCancel):lack of room_id"." in file".__FILE__." on Line ".__LINE__);
            return $this->_missingPrameterArr($operation,"room_id");
        }

        $room_id = $data['room_id'];

        $Redis_Model = Redis_Model::getModelObject();
        $replyArr = array("[roomid]"=>$room_id,"[accountid]"=>$account_id);

        //设置当前状态，已准备
        //更新用户状态
        $rStatus = Game::AccountStatus_Notready;
        $this->updateAccountStatus($room_id, $account_id, $rStatus);

        $ready_count = $this->queryReadyCount($room_id);
        if($ready_count < 2){
            //取消倒计时
            $this->deleteRoomTimer($room_id);
            $arr = array("result"=>0,"operation"=>"CancelStartLimitTime","data"=>array(),"result_message"=>"取消开局倒计时");
            $this->pushMessageToGroup($room_id, $arr);
        }

        return OPT_CONST::NO_RETURN;
    }

    /*
        最后一局积分榜
    */
    public function lastScoreboard($arrData)
    {
        $result = array();

        $data 			= $arrData['data'];
        $operation 		= $arrData['operation'];
        $account_id 	= $arrData['account_id'];
        $client_id 		= $arrData['client_id'];

        $session 		= $arrData['session'];
        $Verification_Model = Verification_Model::getModelObject();
        if(false == $Verification_Model->checkRequestSession($account_id,$session))
        {
            return OPT_CONST::NO_RETURN;
        }

        if(!(isset($data['room_number'])&& $data['room_number'] > 0) )
        {
            $this->logMessage('error', "function(lastScoreboard):lack of room_number"." in file".__FILE__." on Line ".__LINE__);
            return $this->_missingPrameterArr($operation,"room_number");
        }

        $room_number = $data['room_number'];
        $MMYSQL = $this->initMysql();
        //判断房间申请记录是否存在
        $room_where = 'room_number='.$room_number;
        $room_sql = 'select room_id,account_id,is_close from '.Room.' where '.$room_where;
        $room_query = $MMYSQL->query($room_sql);
        if(!is_array($room_query) || count($room_query) == 0 )
        {
            $this->writeLog("function(lastScoreboard):room($room_number) not exist"." in file".__FILE__." on Line ".__LINE__);
            return array("result"=>OPT_CONST::FAILED,"operation"=>$operation,"data"=>$result,"result_message"=>"房间不存在");
        }else{
            $room_id = $room_query[0]['room_id'];
        }

        $scoreboards = new stdClass();
        $sql = 'select board,create_time,game_num,rule_text from room_scoreboard where room_id='.$room_id.' and game_type='.Game::Game_Type.' order by create_time desc limit 1';
        $query = $MMYSQL->query($sql);
        if(!is_array($query) )
        {
            $this->writeLog("function(lastScoreboard):room($room_id) not exist"." in file".__FILE__." on Line ".__LINE__);
        }else{
            foreach ($query as $row) {

                $name_board = array();
                $scoreboard = json_decode($row['board']);
                $create_time = $row['create_time'];
                $game_num = $row['game_num'];
                if($game_num <= 0)
                {
                    $game_num = Config::GameNum_EachRound;
                }

                $total_num = "";
                $rule_text = $row['rule_text'];
                $rule_text_array = explode('局/',$rule_text);
                if(is_array($rule_text_array) && count($rule_text_array) > 0)
                {
                    $total_num = $rule_text_array[0];
                }

                if($scoreboard){
                    foreach ($scoreboard as $account_id => $score) {
                        $account_sql = 'select nickname from '.WX_Account.' where account_id ='.$account_id;
                        $name = $MMYSQL->single($account_sql);
                        $name_board[] = array('name'=>$name, 'score'=>$score, 'account_id'=>$account_id);
                    }
                    $scoreboards = array('time'=>$create_time, 'scoreboard'=>$name_board,'game_num'=>$game_num,'total_num'=>$total_num);
                }
            }
        }

        return array("result"=>"0","operation"=>$operation,"data"=>$scoreboards,"result_message"=>"历史积分榜");
    }
    public function closeRoom($arrData)
    {
        $operation = $arrData['operation'];
        $data = $arrData['data'];
        $account_id = $arrData['account_id'];
        $room_number = $data['room_number'];

        $MMYSQL = $this->initMysql();

        $room_where = 'room_number='.$room_number.' and is_close =0';
        $room_sql = 'select room_id,account_id,is_close from '.Room.' where '.$room_where;
        $room_query = $MMYSQL->query($room_sql);
        if(!is_array($room_query) || count($room_query) == 0 )
        {
            $this->writeLog("function(closeRoomManager):room($room_number) not exist"." in file".__FILE__." on Line ".__LINE__);
            return array("result"=>OPT_CONST::FAILED,"operation"=>$operation,"data"=>[],"result_message"=>"房间不存在");
        }else{
            $room_id = $room_query[0]['room_id'];
        }

        if ($room_query[0]['account_id'] != $account_id){
            $this->writeLog("function(closeRoomManager):room($room_number) no auth"." in file".__FILE__." on Line ".__LINE__);
            return array("result"=>OPT_CONST::FAILED,"operation"=>$operation,"data"=>[],"result_message"=>"不是管理员，不能关闭房间");
        }

        $this->writeLog("[$room_id] 触发群主清房间");

        $MMYSQL = $this->initMysql();
        $Redis_Model = Redis_Model::getModelObject();
        $replyArr = array("[roomid]"=>$room_id);
        $RoomScore_Key = strtr(Redis_Const::RoomScore_Key, $replyArr);

        $game_num = $this->queryGameNumber($room_id);
        $creator = $this->queryCreator($room_id);

        if(Config::Ticket_Mode==2 && $game_num==0 && $creator>0){
            $spend_ticket_count = $this->queryTicketCount($room_id);
            $this->balanceTicket($room_id, $creator, - $spend_ticket_count *Config::Ticket_Multi);
        }

        //保存积分榜
        if($game_num > 0){

            $Room_Key = strtr(Redis_Const::Room_Key, $replyArr);
            $round = $Redis_Model->hincrbyField($Room_Key, Redis_Const::Room_Field_GameRound, 1);
            $this->writeLog("[$room_id] 第".($round-1)."轮 结束!");

            $setting = $this->queryRoomSetting($room_id);
            //$round = $setting['ground'];
            $game_info['room_id'] = $room_id;
            $game_info['game_type'] = Game::Game_Type;
            $game_info['round'] = $round-1;

            $scoreboard = array();
            if(isset($setting['scoreboard']) && $setting['scoreboard']){
                $board_json_str = $setting['scoreboard'];
                $scoreboard = json_decode($board_json_str, true); //转为关联数组
            } else {
                //积分榜为空
                $scoreboard = array();
                $board_json_str = "";
            }
            $name_board = array();
            foreach ($scoreboard as $account_id => $score) {
                $account_sql = 'select nickname from '.WX_Account.' where account_id ='.$account_id;
                $name = $MMYSQL->single($account_sql);
                $name_board[] = array('name'=>$name, 'score'=>$score, 'account_id'=>$account_id);
            }

            //规则文本
            $rule_text = $this->formatRuleText($room_id);
            $balance_scoreboard = array('time'=>time(), 'scoreboard'=>$name_board,'game_num'=>$game_num);
            $balance_board_json_str = json_encode($balance_scoreboard['scoreboard']);

            $start_time = $this->queryStartTime($room_id);

            $board_array['start_time'] = $start_time;
            $board_array['create_time'] = time();
            $board_array['is_delete'] = G_CONST::IS_FALSE;
            $board_array['game_type'] = Game::Game_Type;
            $board_array['room_id'] = $room_id;
            $board_array['round'] = $round - 1;
            $board_array['game_num'] = $game_num;
            $board_array['rule_text'] = $rule_text;
            $board_array['board'] = $board_json_str;
            $board_array['balance_board'] = $balance_board_json_str;
            $board_id = $MMYSQL->insertReturnID(Room_Scoreboard,$board_array);

            //保存用户积分
            $game_info['score_board'] = $scoreboard;
            $this->saveAccountGameScore($game_info);
        }
//关闭房间
        Gateway::closeCurrentClient();
        $client_list = Gateway::getClientInfoByGroup($room_id);
        foreach ($client_list as $client_id => $item) {
            Gateway::closeClient($client_id);
        }
        //清理房间
        $this->clearRoom($room_id);

        return true;
    }
}